//
//  GCDTestController.m
//  Objc进阶Demo
//
//  Created by Don't update on 2018/7/18.
//  Copyright © 2018年 Don't update. All rights reserved.
//

#import "GCDTestController.h"

@interface GCDTestController ()<UITableViewDelegate,UITableViewDataSource>
@property(nonatomic,strong)UITableView *tableView;
@property(nonatomic,strong)NSArray *list;
@end

@implementation GCDTestController

-(NSArray *)list{
    if (_list == nil) {
        _list = [[NSArray alloc]initWithObjects:@"一次性执行(dispatch_once_t)",@"延时操作",@"创建队列", nil];
    }
    return _list;
}

-(UITableView *)tableView{
    if (_tableView == nil) {
        _tableView = [[UITableView alloc]initWithFrame:self.view.bounds style:UITableViewStyleGrouped];
        _tableView.delegate = self;
        _tableView.dataSource = self;
        [self list];
        [self.view addSubview:_tableView];
    }
    return _tableView;
}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return _list.count;
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    static NSString *identifity = @"cell_id";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifity];
    if (cell == nil) {
        cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifity];
    }
    cell.textLabel.text = _list[indexPath.row];
    return  cell;
}

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    switch (indexPath.row) {
        case 0:

            NSLog(@"一次性执行(dispatch_once_t)");
            [self onceTest];
            break;
        case 1:
            NSLog(@"延时操作");
            [self doSomethingAfterTime];
        case 2:
            NSLog(@"创建队列");
            [self createQueue];
            break;
        default:
            break;
    }
}



//一次执行 经常用于创建单例 无论开启多少线程 都只执行一次
-(void)onceTest{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSLog(@"该方法只会调用一次");
    });
}

//延时操作
-(void)doSomethingAfterTime{
    //只是延时提交到队列中而不是延时执行任务
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"执行一次");
    });
}


/* 串行队列与并行队列的区别
 * 1.并行队列 Concurrent Dispatch Queue
 *   可以让多个任务并发执行提高执行效率
 *   并发功能仅在异步(dispatch_async) 函数下才有效
 *
 * 2.串行队列 Serial Dispatch Queue
 *   在当前线程中让任务一个接着一个执行
 */




-(void)createQueue{
    /*
     * 创建队列
     * 参数1: 队列名称
     * 参数2: 队列属性, 可以直接写成NULL
     * 同步任务 dispatch_sync
     * 线程number=1，不开启线程；脚标从0到9，顺序执行任务。
     */
    //创建串行队列的两种方式
    //1.直接创建并串行队列
    dispatch_queue_t queue =  dispatch_queue_create("串行队列", DISPATCH_QUEUE_SERIAL);
    
    //2.获取全局串行队列
    //    dispatch_queue_t queue = dispatch_get_main_queue();
    
    //创建并行对量方式同上2种  DISPATCH_QUEUE_CONCURRENT
    
}

//异步函数,并行队列
-(void)asyncConcurrent{
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(queue, ^{
        for (NSInteger i = 0; i<10; i++) {
            NSLog(@"1-----%@", [NSThread currentThread]);
        }
    });
    dispatch_async(queue, ^{
        for (NSInteger i = 0; i<10; i++) {
            NSLog(@"1-----%@", [NSThread currentThread]);
        }
    });
    NSLog(@"asyncConcurrent-------end");
}

//异步函数,串行队列
-(void)asyncSerial{
    dispatch_queue_t queue = dispatch_queue_create("异步串行队列", DISPATCH_QUEUE_SERIAL);
    
    //通过异步函数将任务加入队列
    dispatch_async(queue, ^{
        NSLog(@"1-----%@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"2-----%@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"3-----%@", [NSThread currentThread]);
    });
}

//异步函数+主队列
-(void)asyncMain{
    dispatch_queue_t queue = dispatch_get_main_queue();
    
    //通过异步函数将任务加入主队列
    dispatch_async(queue, ^{
          NSLog(@"1-----%@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"2-----%@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"3-----%@", [NSThread currentThread]);
    });
    //不会开启子线程 任务是有序执行
}


/* 同步函数,并行队列
 * 不会开启子线程,任务是有序执行
 */
-(void)syncConcurrent{
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    //通过同步函数将任务加入队列
    dispatch_sync(queue, ^{
        NSLog(@"1------%@",[NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"2------%@",[NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"3------%@",[NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"4------%@",[NSThread currentThread]);
    });
    
    //证明 同步函数添加任务到队列中,任务立马执行
    NSLog(@"syncConcurrent--------end");
}

/* 同步函数+串行队列
 * 容易发生死锁,使用时要注意
 */
-(void)syncMain{
    dispatch_queue_t queue = dispatch_queue_create("同步串行队列",DISPATCH_QUEUE_SERIAL);
    
    dispatch_sync(queue, ^{
        NSLog(@"1------%@",[NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"2------%@",[NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"3------%@",[NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"4------%@",[NSThread currentThread]);
    });
    
    /* 以上的用法都不会发生死锁
     * 虽然是在主线程上执行.但是任务在不同的队列中所以不会发生阻塞
     * syncMain 函数在主队列中
     * 其他的任务是是在新建的串行队列中
     *
     * 死锁的几种情况
     * 使用同步函数在执行任务过程中往任务所在的串行队列中添加任务就会导致任务间相互等待,造成死锁
     * 在同步函数任务添加到队列中,任务会立即执行,如果是异步函数就不会发生死锁
     */
}

//GCD实现线程间的通信
-(void)threadCommunication{
    //全局并发队列
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    dispatch_async(queue, ^{
        //执行任务 ....
        
        //回到主线程
        dispatch_async(dispatch_get_main_queue(), ^{
            //coding...
            
            dispatch_async(queue, ^{
                //coding ...
            });
        });
    });
}

//dispatch_barrier_async
/*
 * 必须是并行队列,且不能使用全局的并行队列,实践证明并不管用
 * 函数作用: 再次函数前面的任务执行完成后此函数才开始执行,在此函数后面的任务等此函数执行完成之后才会执行
 */
-(void)barrierDemo{
    dispatch_queue_t queue = dispatch_queue_create("阻塞", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_async(queue, ^{
        NSLog(@"----1-----%@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"----2-----%@",[NSThread currentThread]);
    });
    
}


- (void)viewDidLoad {
    [super viewDidLoad];
    [self tableView];
}



@end
